Skip Headers

Oracle® Database JPublisher User's Guide 10g Release 2 (10.2) Part Number B14188-01 |
Home | Book List | Contents | Index | Master Index | Feedback

Previous | Next
| View PDF

# 4 Generated Classes and Interfaces

This chapter describes the classes, interfaces, and subclasses that JPublisher generates in the following sections:

- Treatment of Output Parameters

- Translation of Overloaded Methods

- Generation of SQLJ Classes

- Generation of Non-SQLJ Classes

- Generation of Java Interfaces

- JPublisher Subclasses

- Support for Inheritance

## 4.1 Treatment of Output Parameters

Stored procedures called through Java Database Connectivity (JDBC) do not pass parameters in the same way as ordinary Java methods. This affects the code that you write when you call a wrapper method that JPublisher generates.

When you call an ordinary Java method, parameters that are Java objects are passed as object references. The method can modify the object.

However, when you call a stored procedure through JDBC, a copy of each parameter is passed to the stored procedure. If the procedure modifies any parameters, then a copy of the modified parameter is returned to the caller. Therefore, the before and after values of a modified parameter appear in separate objects.

A wrapper method that JPublisher generates contains JDBC statements to call the corresponding stored procedure. The parameters to the stored procedure, as declared in your `CREATE TYPE` or `CREATE PACKAGE` declaration, have the following possible parameter modes: `IN`, `OUT`, and `IN OUT`. Parameters that are `IN OUT` or `OUT` are returned to the wrapper method in newly created objects. These new values must be returned to the caller somehow, but assignment to the formal parameter within the wrapper method does not affect the actual parameter visible to the caller.

In Ja va, there are no `OUT` or `IN OUT` designations, but values can be returned through holders. In JPublisher, you can specify one of the following alternatives for holders that handle PL/SQL `OUT` or `IN OUT` parameters:

- Arrays

- Java API for XML-based Remote Procedure Call (JAX-RPC) holder types

- Function returns

The `-outarguments` option enables you to specify which mechanism to use. This feature is particularly useful for Web services.

See Also: "Holder Types for Output Arguments"

The following sections describe the three mechanisms:

- Passing Output Parameters in Arrays

- Passing Output Parameters in JAX-RPC Holders

- Passing Output Parameters in Function Returns

### 4.1.1 Passing Output Parameters in Arrays

One way to solve the problem of returning output values in Java is to pass an `OUT` or `IN OUT` parameter to the wrapper method in a single-element array. Think of the array as a container that holds the parameter. This mechanism works as follows:

1. You assign the before value of the parameter to element `[0]` of an array.

2. You pass the array to your wrapper method.

3. The wrapper method assigns the after value of the parameter to element `[0]` of the array.

4. After running the method, you extract the after value from the array.

A setting of `-outarguments=array`, which is the default, instructs JPublisher to use this single-element array mechanism to publish any `OUT` or `IN OUT` argument.

For example:

    Person [] pa = {p};
    x.f(pa);
    p = pa[0];

Assume that `x` is an instance of a JPublisher-generated class that has the `f()` method, which is a wrapper method for a stored procedure that uses a SQL `PERSON` object as an `IN OUT` parameter. The `PERSON` type maps to the `Person` Java class. `p` is a `Person` instance, and `pa[]` is a single-element `Person` array.

This mechanism for passing `OUT` or `IN OUT` parameters requires you to add a few extra lines of code to your program for each parameter. As another example, consider the PL/SQL function created by the following SQL*Plus command:

    SQL> CREATE OR REPLACE FUNCTION g (
                a0 NUMBER,
                a1 OUT NUMBER,
                a2 IN OUT NUMBER,
                a3 CLOB,
                a4 OUT CLOB,
                a5 IN OUT CLOB)
         RETURN CLOB IS
         BEGIN
                RETURN NULL;
         END;

With `-outarguments=array`, this is published as follows:

    public oracle.sql.CLOB g (
         java.math.BigDecimal a0,
         java.math.BigDecimal a1[],
         java.math.BigDecimal a2[],
         oracle.sql.CLOB a3,
         oracle.sql.CLOB a4[],
         oracle.sql.CLOB a5[])

Problems similar to those described earlier arise when the `this` object of an instance method is modified.

The `this` object is an additional parameter, which is passed in a different way. Its mode, as declared in the `CREATE TYPE` statement, may be `IN` or `IN OUT`. If you do not explicitly declare the mode of the `this` object, then its mode is `IN OUT`, if the stored procedure does not return a result, or `IN`, if it does.

If the mode of the `this` object is `IN OUT`, then the wrapper method must return the new value of `this`. The code generated by JPublisher implements this functionality in different ways, depending on the situation, as follows:

- For a stored procedure that does not return a result, the new value of `this` is returned as the result of the wrapper method.

  As an example, assume that the SQL object type `MYTYPE` has the following member procedure:

      MEMBER PROCEDURE f1(y IN OUT INTEGER);

  Also, assume that JPublisher generates a corresponding Java class, `MyJavaType`. This class defines the following method:

      MyJavaType f1(int[] y)

  The `f1()` method returns the modified `this` object value as a `MyJavaType` instance.

- For a stored function, which is a stored procedure that returns a result, the wrapper method returns the result of the stored function as its result. The new value of `this` is returned in a single-element array, passed as an extra argument, which is the last argument, to the wrapper method.

  Assume that the SQL object type `MYTYPE` has the following member function:

      MEMBER FUNCTION f2(x IN INTEGER) RETURNS VARCHAR2;

  Then the corresponding Java class, `MyJavaType`, defines the following method:

      String f2(int x, MyJavaType[] newValue)

  The `f2()` method returns the `VARCHAR2` value as a Java string and the modified `this` object value as an array element in the `MyJavaType` array.

Note: For PL/SQL static procedures or functions, JPublisher generates instance methods, and not static methods, in the wrapper class. This is the logistic for associating a database connection with each wrapper class instance. The connection instance is used in initializing the wrapper class instance so that you are not subsequently required to explicitly provide a connection or connection context instance when calling wrapper methods.

### 4.1.2 Pas sing Output Parameters in JAX-RPC Holders

The JAX-RPC specification explicitly specifies holder classes in the `javax.xml.rpc.holders` package for the Java mapping of simple XML data types and other types. Typically, `Holder` is appended to the type name for the holder class name. For example, `BigDecimalHolder` is the holder class for `BigDecimal`.

Given a setting of `-outarguments=holder`, JPublisher uses holder instances to publish `OUT` and `IN OUT` arguments from stored procedures. Holder settings are specified in a JPublisher style file. The settings are specified in the `HOLDER` subtag inside the `TARGETTYPE` section for appropriate mapping. If no holder class is specified, then JPublisher chooses one according to defaults.

See Also: "JPublisher Styles and Style Files"

For general information about JAX-RPC and holders, refer to the Java API for XML-based RPC, JAX-RPC 1.0 specification, available at:

`http://jcp.org/aboutJava/communityprocess/final/jsr101/index.html`

As an example, consider the PL/SQL function created by the following SQL*Plus command:

    SQL> CREATE OR REPLACE FUNCTION g (
                a0 NUMBER,
                a1 OUT NUMBER,
                a2 IN OUT NUMBER,
                a3 CLOB,
                a4 OUT CLOB,
                a5 IN OUT CLOB)
         RETURN CLOB IS
         BEGIN
                RETURN NULL;
         END;

Assume that the `webservices10` style file contains an entry for `-outarguments=holder` and the following JPublisher command is used to publish the function, `g()`:

    % jpub -u scott/tiger  -s toplevel"(g)":ToplevelG -style=webservices10

The published interface is:

    public java.lang.String g
                  (java.math.BigDecimal a0,
                   javax.xml.rpc.holders.BigDecimalHolder _xa1_out_x,
                   javax.xml.rpc.holders.BigDecimalHolder _xa2_inout_x,
                   java.lang.String a3,
                   javax.xml.rpc.holders.StringHolder _xa4_out_x,
                   javax.xml.rpc.holders.StringHolder _xa5_inout_x)
    throws java.rmi.RemoteException;

In this case, there is an extra level of abstraction. Because `oracle.sql.CLOB` is not supported by Web services, it is mapped to `String`, the JAX-RPC holder class for which is `StringHolder`.

See Also: "JPublisher-Generated Subclasses for Java-to-Java Type Transformations"

### 4.1.3 Passing Output Parameters in Function Returns

You can use the `-outarguments=return` setting as a workaround for supporting method signatures in Web services that do not use JAX-RPC holder types or arrays. If there is no support for JAX-RPC holders, the `-outarguments=return` setting allows `OUT` or `IN OUT` data to be returned in function results.

Consider the PL/SQL function created by the following SQL*Plus command:

    SQL> CREATE OR REPLACE FUNCTION g (
                a0 NUMBER,
                a1 OUT NUMBER,
                a2 IN OUT NUMBER,
                a3 CLOB,
                a4 OUT CLOB,
                a5 IN OUT CLOB)
         RETURN CLOB IS
         BEGIN
                RETURN NULL;
         END;

Assume the following JPublisher command to publish the function, `g()`. Although the `webservices10` style file specifies `-outarguments=holder`, the `-outarguments=return` setting comes after the `-style` setting and, therefore, takes precedence.

    % jpub -u scott/tiger  -s toplevel"(g)":ToplevelG -style=webservices10
           -outarguments=return

The JPublisher output is as follows:

    SCOTT.top_level_scope
    ToplevelGUser_g_Out

The JPublisher output acknowledges that it is processing the `SCOTT` top level and also indicates the creation of the `ToplevelGUser_g_Out` Java class to support output values of the `g()` function through return data.

Notes: The `_g_Out` appended to the user class name is according to the JPublisher naming convention used when creating a class to contain the output data in the scenario of passing output parameters in function returns. The `_g` reflects the name of the function being processed and the `_Out` reflects the `OUT` modifier in the corresponding PL/SQL call specification. Therefore, `ToplevelGUser_g_Out` is the Java type created for the output data of the `g()` method in the `ToplevelGUser` class. The user class name is according to the naming convention specified in the `webservices10` style file. Typically, JPublisher output reflects only the names of SQL or PL/SQL entities being processed, but there is no such entity that directly corresponds to `ToplevelGUser_g_Out`.

JPublisher generates the following interface to take input parameters and return output parameters:

    public ToplevelGUser_g_Out g
                (java.math.BigDecimal a0,
                 java.math.BigDecimal xxa2_inoutxx,
                 java.lang.String a3,
                 java.lang.String xxa5_inoutxx)
    throws java.rmi.RemoteException;

JPublisher generates the `TopLevelGUser_g_Out` class as follows:

    public class ToplevelGUser_g_Out{
      public ToplevelGUser_g_Out() { }
      public java.math.BigDecimal getA1Out()  { return a1_out; }
      public void setA1Out(java.math.BigDecimal a1_out) { this.a1_out = a1_out; }
      public java.math.BigDecimal getA2Inout()   { return a2_inout; }
      public void setA2Inout(java.math.BigDecimal a2_inout)
                              { this.a2_inout = a2_inout; }
      public java.lang.String getA4Out()   { return a4_out; }}

The `ToplevelGUser_g_Out` return type encapsulates the values of the `OUT` and `IN OUT` parameters to be passed back to the caller of the function. As in the preceding section, `oracle.sql.CLOB` is mapped to `String` by the `webservices10` style file.

## 4.2 Tra nslation of Overloaded Methods

PL/SQL, like Java, lets you create overloaded methods, meaning two or more methods with the same name but different signatures. However, overloaded methods with different signatures in PL/SQL may have identical signatures in Java, especially in user subclasses. As an example, consider the following PL/SQL stored procedures:

    PROCEDURE foo(x SYS.XMLTYPE);
    PROCEDURE foo(x CLOB);
    PROCEDURE foo(x NCHAR);

If you process these with a JPublisher setting of `-style=webservices-common`, then they will all have the same signature in Java:

    void foo(String x);
    void foo(String x);
    void foo(String x);

See Also: "Style File Specifications and Locations"

JPublisher solves such naming conflicts by appending the first letter of the return type and the first letter of each argument type, as applicable, to the method name. If conflicts still remain, then a number is also appended. JPublisher solves the preceding conflict as follows:

    void foo(String x);
    void fooS(String x);
    void fooS1(String x);

Note that PL/SQL does not allow overloading for types from the same family. The following, for example, is illegal:

    PROCEDURE foo(x DECIMAL);
    PROCEDURE foo(x INT);
    PROCEDURE foo(x INTEGER);

Now, consider the procedures as functions instead, with return types from the same family. The following example is allowed because the argument types are different:

    FUNCTION foo(x FLOAT) RETURN DECIMAL;
    FUNCTION foo(x VARCHAR2) RETURN INT;
    FUNCTION foo(x Student_T) RETURN INTEGER;

By default, these are mapped to Java methods as follows:

    java.math.BigDecimal foo(Float x);
    java.math.BigDecimal foo(String x);
    java.math.BigDecimal foo(StudentT x);

JPublisher allows them all to be named `foo()` because now the signatures differ. However, if you want all method names to be unique, as is required for Web services, use the `unique` setting of the JPublisher `-methods` option. With `-methods=unique`, JPublisher publishes the methods as follows, using the naming mechanism described earlier:

    java.math.BigDecimal foo(Float x);
    java.math.BigDecimal fooBS(String x);
    java.math.BigDecimal fooBS1(StudentT x);

See Also: "Generation of Package Classes and Wrapper Methods"

## 4.3 Gen eration of SQLJ Classes

For the `-methods=all` setting, which is the default, or the `-methods=true` setting, JPublisher typically generates SQLJ classes for PL/SQL packages and object types, using both `ORAData` and `SQLData` implementations. An exception is that a SQLJ class is not generated if an object type does not define any methods, in which case the generated Java class does not require the SQLJ run time.

SQLJ classes include wrapper methods that invoke the server methods, or stored procedures, of object types and packages. This section describes how to use these classes.

See Also: "JPublisher Usage of the SQLJ Implementation" and "Backward Compatibility Option"

This section covers the following topics:

- Important Notes About Generation of SQLJ Classes

- Use of SQLJ Classes for PL/SQL Packages

- Use of SQLJ Classes for Object Types

- Connection Contexts and Instances in SQLJ Classes

- The setFrom(), setValueFrom(), and setContextFrom() Methods

### 4.3.1 Important Notes About Generation of SQLJ Classes

Note the following for JPublisher-generated SQLJ classes:

- If you are generating Java wrapper classes for a SQL type hierarchy and any of the types contains stored procedures, then by default, JPublisher generates SQLJ classes for all the SQL types and not just the types that have stored procedures.

  Note: You have the option of explicitly suppressing the generation of SQLJ classes through the JPublisher `-methods=false` setting. This results in all non-SQLJ classes.

- Classes produced by JPublisher include a `release()` method. If an instance of a JPublisher-generated wrapper class implicitly constructs a `DefaultContext` instance, then you should use the `release()` method to release this connection context instance when it is no longer needed. However, you can avoid this scenario by adhering to at least one of the following suggestions in creating and using the wrapper class instance:

  - Construct the wrapper class instance with an explicitly provided SQLJ connection context.

  - Associate the wrapper class instance explicitly with a SQLJ connection context instance through the `setConnectionContext()` method.

  - Use the static SQLJ default connection context instance implicitly for the wrapper class instance. This occurs if you do not supply any connection information.

  See Also: "Connection Contexts and Instances in SQLJ Classes"

- In the Oracle8i compatibility mode, instead of the constructor taking a `DefaultContext` instance or an instance of a user-specified class, there is a constructor that simply takes a `ConnectionContext` instance. This could be an instance of any class that implements the standard `sqlj.runtime.ConnectionContext` interface, including the `DefaultContext` class.

### 4.3.2 Use of SQLJ Classes for PL/SQL Packages

Take the following steps to use a class that JPublisher generates for a PL/SQL package:

1. Construct an instance of the class.

2. Call the wrapper methods of the class.

The constructors for the class associate a database connection with an instance of the class. One constructor takes a SQLJ `DefaultContext` instance or an instance of a class specified through the `-context` option when you run JPublisher. Another constructor takes a JDBC `Connection` instance. One constructor has no arguments. Calling the no-argument constructor is equivalent to passing the SQLJ default context to the constructor that takes a `DefaultContext` instance. JPublisher provides the constructor that takes a `Connection` instance for the convenience of JDBC programmers unfamiliar with SQLJ concepts, such as connection contexts and the default context.

See Also: "Important Notes About Generation of SQLJ Classes"

The wrapper methods are all instance methods, because the connection context in the `this` object is used in the wrapper methods.

Because a class generated for a PL/SQL package has no instance data other than the connection context, you typically construct one class instance for each connection context that you use. If the default context is the only one you use, then you can call the no-argument constructor once.

An instance of a class generated for a PL/SQL package does not contain copies of the PL/SQL package variables. It is not an `ORAData` class or a `SQLData` class, and you cannot use it as a host variable.

### 4.3.3 Use of SQLJ Classes for Object Types

To use an instance of a Java class that JPublisher generates for a SQL object type or a SQL `OPAQUE` type, you must first initialize the Java object. You can accomplish this in one of the following ways:

- Assign an already initialized Java object to your Java object.

- Retrieve a copy of a SQL object into your Java object. You can do this by using the SQL object as an `OUT` argument or as the function return of a JPublisher-generated wrapper method. You can also do this by retrieving the SQL object through JDBC calls that you write. If you are in a backward-compatibility mode and use SQLJ source files directly, then you can retrieve a copy of a SQL object through the SQLJ `#sql` statements.

- Construct the Java object with the no-argument constructor and set its attributes by using the `set` `XXX``()` methods, or construct the Java object with the constructor that accepts values for all the object attributes. Subsequently, you need to use the `setConnection()` or `setConnectionContext()` method to associate the object with a database connection before calling any of its wrapper methods. If you do not explicitly associate the object with a JDBC or SQLJ connection before calling a method on it, then it becomes implicitly associated with the SQLJ default context.

  Other constructors for the class associate a connection with the class instance. One constructor takes a `DefaultContext` instance or an instance of a class specified through the `-context` option when you run JPublisher, and one constructor takes a `Connection` instance. The constructor that takes a `Connection` instance is provided for the convenience of JDBC programmers unfamiliar with SQLJ concepts, such as connection contexts and the default context.

See Also: "Important Notes About Generation of SQLJ Classes"

Once you have initialized your Java object, you can do the following:

- Call the accessor methods of the object.

- Call the wrapper methods of the object.

- Pass the object to other wrapper methods.

- Use the object as a host variable in JDBC calls. If you are in a backward-compatibility mode and use SQLJ source files directly, then you can use the object as a host variable in the SQLJ `#sql` statements.

There is a Java attribute for each attribute of the corresponding SQL object type, with the `get` `XXX``()` and `set` `XXX``()` accessor methods for each attribute. JPublisher does not generate fields for the attributes. For example, for an attribute called `foo`, there is a corresponding Java attribute called `foo` and the accessor methods, `getFoo()` and `setFoo()`.

By default, the class includes wrapper methods that call the associated Oracle object methods, which reside and run on the server. Irrespective of what the server methods are, the wrapper methods are all instance methods. The `DefaultContext` in the `this` object is used in the wrapper methods.

With Oracle mapping, JPublisher generates the following methods for the Oracle JDBC driver to use:

- `create()`

- `toDatum()`

These methods are specified in the `ORAData` and `ORADataFactory` interfaces and are generally not intended for your direct use. In addition, JPublisher generates the `setFrom(``otherObject``)`, `setValueFrom(``otherObject``)`, and `setContextFrom(``otherObject``)` methods that you can use to copy values or connection information from one object instance to another.

### 4.3.4 Connection Co ntexts and Instances in SQLJ Classes

The class that JPublisher uses in creating SQLJ connection context instances depends on how you set the `-context` option when you run JPublisher. The following classes can be used:

- A setting of `-context=DefaultContext`, which is the default setting, results in JPublisher using instances of the standard `sqlj.runtime.ref.DefaultContext` class.

- A setting of a user-defined class that is in `CLASSPATH` and implements the standard `sqlj.runtime.ConnectionContext` interface results in JPublisher using instances of that class.

- A setting of `-context=generated` results in the declaration of the static `_Ctx` connection context class in the JPublisher-generated class. JPublisher uses instances of this class for connection context instances. This is appropriate for the Oracle8i compatibility mode, but generally not recommended.

See Also: "SQLJ Connection Context Classes"

Note: It is no longer a routine, as it was in Oracle8i Database, for JPublisher to declare a `_ctx` connection context instance. However, this is used in the Oracle8i compatibility mode, with `_ctx` being declared as a `protected` instance of the static `_Ctx` connection context class. Unless you have legacy code that depends on `_ctx`, it is preferable to use the `getConnectionContext()` and `setConnectionContext()` methods to retrieve and manipulate connection context instances in JPublisher-generated classes.

Consider the following points in using SQLJ connection context instances or JDBC connection instances in instances of JPublisher-generated wrapper classes:

- Wrapper classes generated by JPublisher provide a `setConnectionContext()` method that you can use to explicitly specify a SQLJ connection context instance. The method is defined as follows:

      void setConnectionContext(conn_ctxt_instance);

  This installs the passed connection context instance as the SQLJ connection context in the wrapper class instance. The connection context instance must be an instance of the class specified through the `-context` setting for JPublisher connection contexts, typically `DefaultContext`.

  Note that the underlying JDBC connection must be compatible with the connection used to materialize the database object in the first place. Specifically, some objects may have attributes that are valid only for a particular connection, such as object reference types or BLOBs.

  If you have already specified a connection context instance through the constructor, then you need not set it again using the `setConnectionContext()` method.

Note: Using the `setConnectionContext()` method to explicitly set a connection context instance avoids the problem of the connection context not being closed properly. This problem occurs only with implicitly created connection context instances.

- Use either of the following methods of a wrapper class instance, as appropriate, to retrieve a connection or connection context instance:

  - `Connection getConnection()`

  - `ConnCtxtType` `getConnectionContext()`

  The `getConnectionContext()` method returns an instance of the connection context class specified through the JPublisher `-context` setting, typically `DefaultContext`.

  The returned connection context instance may be either an explicitly set instance or one that was created implicitly by JPublisher.

Note: These methods are available only in the generated SQLJ classes. If necessary, you can use the setting `-methods=always` to ensure that SQLJ classes are produced.

- If no connection context instance is explicitly set for a JPublisher-generated SQLJ class, then one will be created implicitly from the JDBC connection instance when the `getConnectionContext()` method is called.

  In this circumstance, at the end of processing, you need to use the `release()` method to free resources in the SQLJ run time. This prevents a possible memory leak.

### 4.3.5 The setFrom(), setValu eFrom(), and setContextFrom() Methods

JPublisher provides the following utility methods in the generated SQLJ classes:

- `setFrom(``anotherObject``)`

  This method initializes the calling object from another object of the same base type, including connection and connection context information. An existing, implicitly created connection context object on the calling object is freed.

- `setValueFrom(``anotherObject``)`

  This method initializes the underlying field values of the calling object from another object of the same base type. This method does not transfer connection or connection context information.

- `setContextFrom(``anotherObject``)`

  This method initializes the connection and connection context information on the calling object from the connection setting of another object of the same base type. An existing, implicitly created, connection context object on the calling object is freed. This method does not transfer any information related to the object value.

Note that there is semantic equivalence between the `setFrom()` method and the combination of the `setValueFrom()` and `setContextFrom()` methods.

## 4.4 Generation of Non-SQLJ Classes

For a `-methods=false` setting, or when SQL object types do not define any methods, JPublisher does not generate wrapper methods for object types. In this case, the generated class does not require the SQLJ run time during execution. Therefore, JPublisher generates non-SQLJ classes, meaning classes that do not call the SQLJ run time application programming interfaces (APIs). All this is true regardless of whether you use an `ORAData` implementation or an `SQLData` implementation.

Notes: For the `-methods=false` setting, JPublisher does not generate code for PL/SQL packages, because they are not useful without wrapper methods. JPublisher generates the same Java code for reference, `VARRAY`, and nested table types regardless of whether the `-methods` option is set to `false` or `true`.

To use an instance of a class that JPublisher generates for an object type with the `-methods=false` setting or for a reference, `VARRAY`, or nested table type, you must first initialize the object.

You can initialize your object in one of the following ways:

- Assign an already initialized Java object to your Java object.

- Retrieve a copy of a SQL object into your Java object. You can do this by using the SQL object as an `OUT` argument or as the function return accessed through a JPublisher-generated wrapper method in some other class. You can also do this by retrieving the SQL object through JDBC calls that you write. If you are in a backward-compatibility mode and using SQLJ source files directly, then you can retrieve a copy of a SQL object through the SQLJ `#sql` statements.

- Construct the Java object with a no-argument constructor and initialize its data, or construct the Java object based on its attribute values.

Unlike the constructors generated in SQLJ classes, the constructors generated in non-SQLJ classes do not take a connection argument. Instead, when your object is passed to or returned from a JDBC `Statement`, `CallableStatement`, or `PreparedStatement` object, JPublisher applies the connection it uses to construct the `Statement`, `CallableStatement`, or `PreparedStatement` object.

This does not mean you can use the same object with different connections at different times, which is not always possible. An object may have a subcomponent that is valid only for a particular connection, such as a reference or a `BLOB`.

To initialize the object data, use the `set` `XXX``()` methods, if your class represents an object type, or the `setArray()` or `setElement()` method, if your class represents a `VARRAY` or nested table type. If your class represents a reference type, then you can construct only a null reference. All non-null references come from the database.

Once you have initialized your object, you can do the following:

- Pass the object to wrapper methods in other classes.

- Use the object as a host variable in JDBC calls. If you are in a backward-compatibility mode and use SQLJ source files directly, then you can use the object in the SQLJ `#sql` statements.

- Call the methods that read and write the state of the object. These methods operate on the Java object in your program and do not affect data in the database. You can read and write the state of the object in the following ways:

  - For a class that represents an object type, call the `get` `XXX``()` and `set` `XXX``()` accessor methods.

  - For a class that represents a `VARRAY` or nested table, call the `getArray()`, `setArray()`, `getElement()`, and `setElement()` methods.

    The `getArray()` and `setArray()` methods return or modify an array as a whole. The `getElement()` and `setElement()` methods return or modify individual elements of the array.

    If you want to update the data in the database, then you need to re-insert the Java array into the database.

- You cannot modify an object reference, because it is an immutable entity. However, you can read and write the SQL object that it references by using the `getValue()` and `setValue()` methods.

  The `getValue()` method returns a copy of the SQL object that is being referenced by the object reference. The `setValue()` method updates a SQL object type instance in the database by taking an instance of the Java class that represents the object type as input. Unlike the `get` `XXX``()` and `set` `XXX``()` accessor methods of a class generated for an object type, the `getValue()` and `setValue()` methods read and write SQL objects.

  Note that both `getValue()` and `setValue()` result in a database round trip to read or write the value of the underlying database object that the reference points to.

You can use the `getORADataFactory()` method in the JDBC code to return an `ORADataFactory` object. You can pass this `ORADataFactory` object to the `getORAData()` method in the `ArrayDataResultSet`, `OracleCallableStatement`, and `OracleResultSet` classes in the `oracle.jdbc` package. The Oracle JDBC driver uses the `ORADataFactory` object to create instances of your JPublisher-generated class.

In addition, classes representing `VARRAY` and nested table types have methods that implement features of the `oracle.sql.ARRAY` class. These methods are:

- `getBaseTypeName()`

- `getBaseType()`

- `getDescriptor()`

However, JPublisher-generated classes for `VARRAY` and nested table types do not extend the `oracle.sql.ARRAY` class.

With Oracle mapping, JPublisher generates the following methods for the Oracle JDBC driver to use:

- `create()`

- `toDatum()`

These methods are specified in the `ORAData` and `ORADataFactory` interfaces and are not generally intended for direct use. However, you may want to use them if converting from one object reference Java wrapper type to another.

## 4.5 Gen eration of Java Interfaces

JPublisher has the ability to generate interfaces as well as classes. This feature is especially useful for Web services, because it eliminates the necessity to manually create Java interfaces that represent the API from which WSDL content is generated.

The `-sql` option supports the following syntax:

    -sql=sql_package_or_type:JavaClass#JavaInterface

or:

    -sql=sql_package_or_type:JavaClass:JavaUserSubclass#JavaSubInterface

Whenever an interface name is specified in conjunction with a class, then the public attributes or wrapper methods or both of that class are provided in the interface, and the generated class implements the interface.

See Also: "Publishing User-Defined SQL Types" and "Publishing PL/SQL Packages"

You can specify an interface for either the generated class or the user subclass, but not both. The difference between an interface for a generated base class and one for a user subclass involves Java-to-Java type transformations. Method signatures in the subclass may be different from signatures in the base class because of Java-to-Java mappings.

See Also: "JPublisher Styles and Style Files"

## 4.6 JPublisher Subclasses

In translating a SQL user-defined type, you may want to enhance the functionality of the custom Java class generated by JPublisher.

One way to accomplish this is to manually add methods to the class generated by JPublisher. However, this is not advisable if you anticipate running JPublisher in the future to regenerate the class. If you regenerate a class that you have modified in this way, then your changes, such as the methods you have added, will be overwritten. Even if you direct JPublisher output to a separate file, you still must merge your changes into the file.

The preferred way to enhance the functionality of a generated class is to extend the class. JPublisher has a mechanism for this, where it will generate the original base class along with a stub subclass, which you can customize as desired. Wherever the SQL type is referenced in code, such as when it is used as an argument, the SQL type will be mapped to the subclass rather than to the base class.

There is also a scenario for JPublisher-generated subclasses for Java-to-Java type transformations. You may have situations in which JPublisher mappings from SQL types to Java types use Java types unsuitable for your purposes; for example, types unsupported by Web services. JPublisher uses a mechanism of styles and style files to allow an additional Java-to-Java transformation step, to use a Java type that is suitable.

The following topics are covered in this section:

- Extending JPublisher-Generated Classes

- JPublisher-Generated Subclasses for Java-to-Java Type Transformations

### 4.6.1 Extendi ng JPublisher-Generated Classes

Suppose you want JPublisher to generate the `JAddress` class from the `ADDRESS` SQL object type. You also want to write a class, `MyAddress`, to represent `ADDRESS` objects, where `MyAddress` extends the functionality that `JAddress` provides.

Under this scenario, you can use JPublisher to generate both a base Java class, `JAddress`, and an initial version of a subclass, `MyAddress`, to which you can add the desired functionality. You then use JPublisher to map `ADDRESS` objects to the `MyAddress` class instead of the `JAddress` class.

To do this, JPublisher alters the code it generates in the following ways:

- It generates the `MyAddressRef` reference class instead of `JAddressRef`.

- It uses the `MyAddress` class, instead of the `JAddress` class, to represent attributes with the SQL type `ADDRESS` or to represent `VARRAY` and nested table elements with the SQL type `ADDRESS`.

- It uses the `MyAddress` factory, instead of the `JAddress` factory, when the `ORADataFactory` interface is used to construct Java objects with the SQL type `ADDRESS`.

- It generates or regenerates the code for the `JAddress` class. In addition, it generates an initial version of the code for the `MyAddress` class, which you can then modify to insert your own additional functionality. However, if the source file for the `MyAddress` class already exists, then it is left untouched by JPublisher.

See Also: "Changes in JPublisher Behavior Between Oracle8i Database and Oracle9i Database"

#### 4.6.1.1 Syntax for Mapping to Alternative Classes

JPublisher has the functionality to streamline the process of mapping to alternative classes. Use the following syntax in your `-sql` command-line option setting:

    -sql=object_type:generated_base_class:map_class

For the `MyAddress`/`JAddress` example, it is:

    -sql=ADDRESS:JAddress:MyAddress

If you were to enter the line in the `INPUT` file instead of on the command line, it would look like this:

    SQL ADDRESS GENERATE JAddress AS MyAddress

In this syntax, `JAddress` is the name of the base class that JPublisher generates, in `JAddress.java`, but `MyAddress` is the name of the class that actually maps to `ADDRESS`. You are ultimately responsible for the code in `MyAddress.java`. Update this as necessary to add your custom functionality. If you retrieve an object that has an `ADDRESS` attribute, then this attribute is created as an instance of `MyAddress`. Or, if you retrieve an `ADDRESS` object directly, then it is retrieved into an instance of `MyAddress`.

See Also: "Declaration of Object Types and Packages to Translate" and "INPUT File Structure and Syntax"

#### 4.6.1.2 Format of the Class that Extends the Generated Class

For convenience, an initial version of the user subclass is automatically generated by JPublisher, unless it already exists. This subclass is where you place your custom code. For example, the `MyAddress.java` file generated by JPublisher in the preceding example.

Note the following:

- The class has a no-argument constructor. The easiest way to construct a properly initialized object is to invoke the constructor of the superclass, either explicitly or implicitly.

- The class implements the `ORAData` interface or the `SQLData` interface. This happens implicitly by inheriting the necessary methods from the superclass.

- When extending an `ORAData` class, the subclass also implements the `ORADataFactory` interface, with an implementation of the `create()` method, as shown:

      public ORAData create(Datum d, int sqlType) throws SQLException
      {
         return create(new UserClass(),d,sqlType);
      }

  However, when the class is part of an inheritance hierarchy, the generated method changes to `protected ORAData createExact()`, with the same signature and body as `create()`.

### 4.6.2 JPublisher-Gen erated Subclasses for Java-to-Java Type Transformations

JPublisher style files enable you to specify Java-to-Java type mappings. A typical use for such mappings is to ensure that generated classes can be used in Web services. As a particular example, `CLOB` types, such as `java.sql.Clob` and `oracle.sql.CLOB`, cannot be used in Web services. However, the data can be used if converted to a type that is supported by Web services, such as `java.lang.String`.

If you use the JPublisher `-style` option to specify a style file, then JPublisher generates subclasses that implement the Java-to-Java type mappings specified in the style file. This includes the use of holder classes for handling output arguments and data corresponding to PL/SQL `OUT` or `IN OUT` types.

See Also: "JPublisher Styles and Style Files" and "Passing Output Parameters in JAX-RPC Holders"

For example, consider the following PL/SQL package, `foo_pack`, consisting of the stored function, `foo`:

    CREATE OR REPLACE PACKAGE foo_pack AS
       FUNCTION foo(a IN OUT SYS.XMLTYPE, b INTEGER) RETURN CLOB;
    END;
    /

Assume that you translate the `foo_pack` package as follows:

    % jpub -u scott/tiger -s foo_pack:FooPack -style=webservices10

This command uses the style file `webservices10.properties` for Java-to-Java type mappings. Among other things, the `webservices10.properties` file specifies the following:

- The mapping of the `oracle.sql.SimpleXMLType` Java type, which is not supported by Web services, to the `javax.xml.transform.Source` Java type. This is specified in the style file as follows:

      SOURCETYPE oracle.sql.SimpleXMLType
      TARGETTYPE javax.xml.transform.Source
      ...

- The use of holder classes for PL/SQL `OUT` and `IN OUT` arguments:

      jpub.outarguments=holder

  This setting directs JPublisher to use instances of the appropriate holder class, in this case `javax.xml.rpc.holders.SourceHolder`, for the PL/SQL output argument of the `XMLTYPE` type.

- The inclusion of `webservices-common.properties`:

      INCLUDE webservices-common

Note: This style file is supplied by Oracle and is appropriate for using Web services in an Oracle Database 10g environment.

The `webservices-common.properties` file, which is also supplied by Oracle, specifies the following:

- The mapping of `SYS.XMLTYPE` to `oracle.sql.SimpleXMLType` in the JPublisher default type map:

      jpub.adddefaulttypemap=SYS.XMLTYPE:oracle.sql.SimpleXMLType

- A code generation naming pattern:

      jpub.genpattern=%2Base:%2User#%2

  Based on the `-s foo_pack:FooPack` specification to JPublisher, the `genpattern` setting results in the generation of the `FooPack` interface, the base class `FooPackBase`, and the user subclass `FooPackUser`, which extends `FooPackBase` and implements `FooPack`.

  See Also: "Class and Interface Naming Pattern"

- The mapping of the `oracle.sql.CLOB` Java type, which is not supported by Web services, to the `java.lang.String` Java type:

      SOURCETYPE oracle.sql.CLOB
      TARGETTYPE java.lang.String
      ...

Recall the calling sequence for the stored function `foo`:

    FUNCTION foo(a IN OUT SYS.XMLTYPE, b INTEGER) RETURN CLOB;

The base class generated by JPublisher, `FooPackBase`, has the following corresponding method declaration:

    public oracle.sql.CLOB _foo (oracle.sql.SimpleXMLType a[], Integer b)

The base class uses an array to hold the output argument.

See Also: "Passing Output Parameters in Arrays"

The user subclass has the following corresponding method declaration:

    public java.lang.String foo (SourceHolder _xa_inout_x, Integer b)

This declaration is because of the specified mapping of `oracle.sql.SimpleXMLType` to `javax.xml.transform.Source`, the specified use of holder classes for output arguments, and the specified mapping of `oracle.sql.CLOB` to `java.lang.String`.

The following is the code for the `SourceHolder` class, which is the holder class for `javax.xml.transform.Source`:

    // Holder class for javax.xml.transform.Source
    public class SourceHolder implements javax.xml.rpc.holders.Holder
    {
       public javax.xml.transform.Source value;
       public SourceHolder() { }
       public SourceHolder(javax.xml.transform.Source value)
       { this.value = value; }
    }

Generated user subclasses employ the following general functionality for Java-to-Java type transformations in the wrapper method:

    User subclass method
    {
         Enter Holder layer (extract IN data from the holder)
              Enter Java-to-Java mapping layer (from target to source)
                   Call base class method (uses JDBC to invoke wrapped procedure)
              Exit Java-to-Java mapping layer (from source to target)
         Exit Holder layer (update the holder)
    }

For this example, the `foo()` method of the `FooPackUser` class is defined as follows:

    foo (SourceHolder, Integer)
    {
         SourceHolder -> Source
              Source -> SimpleXMLType
                   _foo (SimpleXMLType[], Integer);
              SimpleXMLType -> Source
         Source -> SourceHolder
    }

Note: Do not confuse the term source with the class name `Source`. In this example, `Source` is a target type and `SimpleXMLType` is the corresponding source type.

The holder layer retrieves and assigns the holder instance.

In the example, the holder layer in `foo()` performs the following:

1. It retrieves a `Source` object from the `SourceHolder` object that is passed in to the `foo()` method.

2. After processing, which occurs inside the type conversion layer, it assigns the `SourceHolder` object from the `Source` object that was retrieved and processed.

The type conversion layer first takes the target type, `TARGETTYPE` from the style file, and converts it to the source type, `SOURCETYPE` from the style file. It then calls the corresponding method in the base class, which uses JDBC to invoke the wrapped stored function. Finally, it converts the source type returned by the base class method back into the target type to return to the holder layer.

In this example, the type conversion layer in `foo()` performs the following:

1. It takes the `Source` object from the holder layer.

2. It converts the `Source` object to a `SimpleXMLType` object.

3. It passes the `SimpleXMLType` object to the `_foo()` method of the base class, which uses JDBC to invoke the `foo` stored function.

4. It takes the `SimpleXMLType` object returned by the `_foo()` method.

5. It converts the `SimpleXMLType` object back to a `Source` object for the holder layer.

See Also: "Generated Code: User Subclass for Java-to-Java Transformations"

## 4.7 Support for Inh eritance

This section describes the inheritance support for the `ORAData` types and explains the following related topics:

- How JPublisher implements support for inheritance

- Why a reference class for a subtype does not extend the reference class for the base type, and how you can convert from one reference type to another reference type, typically a subclass or superclass

This section covers the following topics:

- ORAData Object Types and Inheritance

- ORAData Reference Types and Inheritance

- SQLData Object Types and Inheritance

- Effects of Using SQL FINAL, NOT FINAL, NOT INSTANTIABLE

### 4.7.1 ORAD ata Object Types and Inheritance

Consider the following SQL object types:

    CREATE TYPE PERSON AS OBJECT (
    ...
    ) NOT FINAL;

    CREATE TYPE STUDENT UNDER PERSON (
    ...
    );

    CREATE TYPE INSTRUCTOR UNDER PERSON (
    ...
    );

Consider the following JPublisher command to create corresponding Java classes:

    % jpub -user=scott/tiger
           -sql=PERSON:Person,STUDENT:Student,INSTRUCTOR:Instructor -usertypes=oracle

In this example, JPublisher generates a `Person` class, a `Student` class, and an `Instructor` class. The `Student` and `Instructor` classes extend the `Person` class, because `STUDENT` and `INSTRUCTOR` are subtypes of `PERSON`.

The class at the root of the inheritance hierarchy, `Person` in this example, contains full information for the entire inheritance hierarchy and automatically initializes its type map with the required information. As long as you use JPublisher to generate all the required classes of a class hierarchy together, no additional action is required. The type map of the class hierarchy is appropriately populated.

This section covers the following topics:

- Precautions when Combining Partially Generated Type Hierarchies

- Mapping of Type Hierarchies in JPublisher-Generated Code

#### 4.7.1.1 Precautions when Combining Partially Generated Type Hierarchies

If you run JPublisher several times on a SQL type hierarchy, each time generating only part of the corresponding Java wrapper classes, then you must take precautions in the user application to ensure that the type map at the root of the class hierarchy is properly initialized.

In our previous example, you may have run the following JPublisher commands:

    % jpub -user=scott/tiger -sql=PERSON:Person,STUDENT:Student -usertypes=oracle
    % jpub -user=scott/tiger -sql=PERSON:Person,INSTRUCTOR:Instructor
           -usertypes=oracle

In this case, you should create instances of the generated classes, at least of the leaf classes, before using these mapped types in your code. For example:

    new Instructor(); // required
    new Student();    // required
    new Person();     // optional

#### 4.7.1.2 Mapping of Type Hierarchies in JPublisher-Generated Code

The `Person` class includes the following method:

    Person create(oracle.sql.Datum d, int sqlType)

This method converts a `Datum` instance to its representation as a custom Java object. It is called by the Oracle JDBC driver whenever a SQL object declared to be a `PERSON` is retrieved into a `Person` variable. The SQL object, however, may actually be a `STUDENT` object. In this case, the `create()` method must create a `Student` instance rather than a `Person` instance.

To handle this kind of situation, the `create()` method of a custom Java class must be able to create instances of any subclass that represents a subtype of the SQL object type corresponding to the `oracle.sql.Datum` argument. This ensures that the actual type of the created Java object matches the actual type of the SQL object. The custom Java class may or may not be created by JPublisher.

However, the code for the `create()` method in the root class of a custom Java class hierarchy need not mention the subclasses. In fact, if it did mention the subclasses, then you would have to modify the code for the base class whenever you write or create a new subclass. The base class is modified automatically if you use JPublisher to regenerate the entire class hierarchy. But regenerating the hierarchy may not always be possible. For example, you may not have access to the source code for the Java classes being extended.

Instead, code generated by JPublisher permits incremental extension of a class hierarchy by creating a static initialization block in each subclass of the custom Java class hierarchy. This static initialization block initializes a data structure declared in the root-level Java class, giving the root class the information it needs about the subclass. When an instance of a subclass is created at run time, the type is registered in the data structure. Because of this implicit mapping mechanism, no explicit type map, such as those required in the `SQLData` scenarios, is required.

Note: This implementation makes it possible to extend existing classes without having to modify them, but it also carries a penalty. The static initialization blocks of the subclasses must be processed before the class hierarchy can be used to read objects from the database. This occurs if you instantiate an object of each subclass by calling `new()`. It is sufficient to instantiate just the leaf classes, because the constructor for a subclass invokes the constructor for its immediate superclass. As an alternative, you can generate or regenerate the entire class hierarchy, if it is feasible.

### 4.7.2 ORAD ata Reference Types and Inheritance

This section shows how to convert from one custom reference class to another and also explains why a custom reference class generated by JPublisher for a subtype does not extend the reference classes of the base type.

This section covers the following topics:

- Casting a Reference Type Instance into Another Reference Type

- Why Reference Type Inheritance Does Not Follow Object Type Inheritance

- Manually Converting Between Reference Types

- Example: Manually Converting Between Reference Types

#### 4.7.2.1 Casting a Reference Type Instance into Another Reference Type

Revisiting the example in "ORAData Object Types and Inheritance", `PersonRef`, `StudentRef`, and `InstructorRef` are obtained for strongly typed references, in addition to the underlying object type wrapper classes.

There may be situations in which you have a `StudentRef` instance, but you want to use it in a context that requires a `PersonRef` instance. In this case, use the static method, `cast()`, generated in strongly typed reference classes:

    StudentRef s_ref = ...;
    PersonRef p_ref = PersonRef.cast(s_ref);

Conversely, you may have a `PersonRef` instance and know that you can narrow it to an `InstructorRef` instance:

    PersonRef pr = ...;
    InstructorRef ir = InstructorRef.cast(pr);

#### 4.7.2.2 Why Reference Type Inheritance Does Not Follow Object Type Inheritance

The example here helps explain why it is not desirable for reference types to follow the hierarchy of their related object types. Consider again a subset of the example given in the previous section (repeated here for convenience):

    CREATE TYPE PERSON AS OBJECT (
    ...
    ) NOT FINAL;

    CREATE TYPE STUDENT UNDER PERSON (
    ...
    );

And consider the following JPublisher command:

    % jpub -user=scott/tiger -sql=PERSON:Person,STUDENT:Student -usertypes=oracle

In addition to generating the `Person` and `Student` Java types, JPublisher generates `PersonRef` and `StudentRef` types.

Because the `Student` class extends the `Person` class, you may expect `StudentRef` to extend `PersonRef`. However, this is not the case, because the `StudentRef` class can provide more compile-time type safety as an independent class than as a subtype of `PersonRef`. Additionally, a `PersonRef` object can perform something that a `StudentRef` object cannot, such as modifying a `Person` object in the database.

The most important methods of the `PersonRef` class are the following:

- `Person getValue()`

- `void setValue(Person c)`

The corresponding methods of the `StudentRef` class are as follows:

- `Student getValue()`

- `void setValue(Student c)`

If the `StudentRef` class extended the `PersonRef` class, then the following problems would occur:

- Java would not permit the `getValue()` method in `StudentRef` to return a `Student` object when the method it overrides in the `PersonRef` class returns a `Person` object, even though this is arguably a sensible thing to do.

- The `setValue()` method in `StudentRef` would not override the `setValue()` method in `PersonRef`, because the two methods have different signatures.

You cannot remedy these problems by giving the `StudentRef` methods the same signatures and result types as the `PersonRef` methods, because the additional type safety provided by declaring an object as a `StudentRef`, rather than as a `PersonRef`, would be lost.

#### 4.7.2.3 Manually Converting Between Reference Types

You cannot convert one reference type to another directly, because reference types do not follow the hierarchy of their related object types. This is a limitation of JPublisher. For background information, this section explains how the generated `cast()` methods work to convert from one reference type to another.

Note: It is not recommended that you follow these manual steps. They are presented here for illustration only. You can use the `cast()` method instead.

The following example outlines the code that could be used to convert from the `XxxxRef` reference type to the `YyyyRef` reference type:

    java.sql.Connection conn = ...;  // get underlying JDBC connection
    XxxxRef xref = ...;
    YyyyRef yref = (YyyyRef) YyyyRef.getORADataFactory().
                    create(xref.toDatum(conn),oracle.jdbc.OracleTypes.REF);

This conversion consists of two steps, each of which can be useful in its own right.

1. Convert `xref` from its strong `XxxxRef` type to the weak `oracle.sql.REF` type:

       oracle.sql.REF ref  = (oracle.sql.REF) xref.toDatum(conn);

2. Convert from the `oracle.sql.REF` type to the target `YyyyRef` type:

       YyyyRef yref = (YyyyRef) YyyyRef.getORADataFactory().
                                 create(ref,oracle.jdbc.OracleTypes.REF);

Note: This conversion does not include any type-checking. Whether this conversion is actually permitted depends on your application and on the SQL schema you are using.

#### 4.7.2.4 Example: Manually Converting Between Reference Types

The following example, including the SQL definitions and Java code, illustrates the points of the preceding discussion.

SQL Definitions Consider the following SQL definitions:

    CREATE TYPE person_t AS OBJECT (ssn NUMBER, name VARCHAR2(30), dob DATE) NOT FINAL;
    /
    SHOW ERRORS

    CREATE TYPE instructor_t UNDER person_t (title VARCHAR2(20)) NOT FINAL;
    /
    SHOW ERRORS

    CREATE TYPE instructorPartTime_t UNDER instructor_t (num_hours NUMBER);
    /
    SHOW ERRORS

    CREATE TYPE student_t UNDER person_t (deptid NUMBER, major VARCHAR2(30)) NOT FINAL;
    /
    SHOW ERRORS

    CREATE TYPE graduate_t UNDER student_t (advisor instructor_t);
    /
    SHOW ERRORS

    CREATE TYPE studentPartTime_t UNDER student_t (num_hours NUMBER);
    /
    SHOW ERRORS

    CREATE TABLE person_tab OF person_t;

    INSERT INTO person_tab VALUES (1001, 'Larry', TO_DATE('11-SEP-60'));

    INSERT INTO person_tab VALUES (instructor_t(1101, 'Smith', TO_DATE('09-OCT-1940'), 'Professor'));

    INSERT INTO person_tab VALUES (instructorPartTime_t(1111, 'Myers', TO_DATE('10-OCT-65'), 'Adjunct Professor', 20));

    INSERT INTO person_tab VALUES (student_t(1201, 'John', To_DATE('01-OCT-78'), 11, 'EE'));

    INSERT INTO person_tab VALUES (graduate_t(1211, 'Lisa', TO_DATE('10-OCT-75'), 12, 'ICS', instructor_t(1101, 'Smith', TO_DATE ('09-OCT-40'), 'Professor')));

    INSERT INTO person_tab VALUES (studentPartTime_t(1221, 'Dave', TO_DATE('11-OCT-70'), 13, 'MATH', 20));

JPublisher Mappings Assume the following mappings when you run JPublisher:

    Person_t:Person,instructor_t:Instructor,instructorPartTime_t:InstructorPartTime,
    graduate_t:Graduate,studentPartTime_t:StudentPartTime

SQLJ Class Here is a SQLJ class with an example of reference type conversion:

    import java.sql.*;
    import oracle.jdbc.*;
    import oracle.sql.*;

    public class Inheritance
    {
      public static void main(String[] args) throws SQLException
      {
        System.out.println("Connecting.");
        java.sql.DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
        oracle.jdbc.OracleConnection conn =
                  (oracle.jdbc.OracleConnection) java.sql.DriverManager.getConnection
                  ("jdbc:oracle:oci8:@", "scott", "tiger");
        // The following is only required in 9.0.1
        // or if the Java class hierarchy was created piecemeal
        System.out.println("Initializing type system.");
        new Person();
        new Instructor();
        new InstructorPartTime();
        new StudentT();
        new StudentPartTime();
        new Graduate();
        PersonRef p_ref;
        InstructorRef i_ref;
        InstructorPartTimeRef ipt_ref;
        StudentTRef s_ref;
        StudentPartTimeRef spt_ref;
        GraduateRef g_ref;
        OraclePreparedStatement stmt =
                    (OraclePreparedStatement)conn.prepareStatement
                    ("select ref(p) FROM PERSON_TAB p WHERE p.NAME=:1");
        OracleResultSet rs;

        System.out.println("Selecting a person.");
        stmt.setString(1, "Larry");
        rs = (OracleResultSet) stmt.executeQuery();
        rs.next();
        p_ref = (PersonRef) rs.getORAData(1, PersonRef.getORADataFactory());
        rs.close();

        System.out.println("Selecting an instructor.");
        stmt.setString(1, "Smith");
        rs = (OracleResultSet) stmt.executeQuery();
        rs.next();
        i_ref = (InstructorRef) rs.getORAData(1, InstructorRef.getORADataFactory());
        rs.close();

        System.out.println("Selecting a part time instructor.");
        stmt.setString(1, "Myers");
        rs = (OracleResultSet) stmt.executeQuery();
        rs.next();
        ipt_ref = (InstructorPartTimeRef) rs.getORAData
                  (1, InstructorPartTimeRef.getORADataFactory());
        rs.close();

        System.out.println("Selecting a student.");
        stmt.setString(1, "John");
        rs = (OracleResultSet) stmt.executeQuery();
        rs.next();
        s_ref = (StudentTRef) rs.getORAData(1, StudentTRef.getORADataFactory());
        rs.close();

        System.out.println("Selecting a part time student.");
        stmt.setString(1, "Dave");
        rs = (OracleResultSet) stmt.executeQuery();
        rs.next();
        spt_ref = (StudentPartTimeRef) rs.getORAData
                  (1, StudentPartTimeRef.getORADataFactory());
        rs.close();

        System.out.println("Selecting a graduate student.");
        stmt.setString(1, "Lisa");
        rs = (OracleResultSet) stmt.executeQuery();
        rs.next();
        g_ref = (GraduateRef) rs.getORAData(1, GraduateRef.getORADataFactory());
        rs.close();
        stmt.close();

        // Assigning a part-time instructor ref to a person ref
        System.out.println("Assigning a part-time instructor ref to a person ref");
        oracle.sql.Datum ref = ipt_ref.toDatum(conn);
        PersonRef pref = (PersonRef) PersonRef.getORADataFactory().
                                               create(ref,OracleTypes.REF);
        // or just use: PersonRef pref = PersonRef.cast(ipt_ref);
        // Assigning a person ref to an instructor ref
        System.out.println("Assigning a person ref to an instructor ref");
        InstructorRef iref = (InstructorRef) InstructorRef.getORADataFactory().
                                         create(pref.toDatum(conn), OracleTypes.REF);
        // or just use: InstructorRef iref = InstructorRef.cast(pref);
        // Assigning a graduate ref to an part time instructor ref.
        // This should produce an error, demonstrating that refs
        // are type safe.
        System.out.println ("Assigning a graduate ref to a part time instructor ref");
        InstructorPartTimeRef iptref =
                    (InstructorPartTimeRef) InstructorPartTimeRef.getORADataFactory().
                    create(g_ref.toDatum(conn), OracleTypes.REF);
        // or just use: InstructorPartTimeRef iptref =
        // InstructorPartTimeRef.cast(g_ref);
        conn.close();
      }
    }

### 4.7.3 SQLData Object Types and Inheritance

If you use the JPublisher `-usertypes=jdbc` setting instead of `-usertypes=oracle`, then the custom Java class generated by JPublisher implements the standard `SQLData` interface instead of the Oracle `ORAData` interface. The standard `SQLData` methods, `readSQL()` and `writeSQL()`, provide functionality equivalent to the `ORAData`/`ORADataFactory` methods, `create()` and `toDatum()`, for reading and writing data.

When JPublisher generates `SQLData` classes corresponding to a SQL hierarchy, the Java types follow the same hierarchy as the SQL types. This is similar to the case when JPublisher generates `ORAData` classes corresponding to a hierarchy of SQL object types. However, `SQLData` implementations do not offer the implicit mapping intelligence that JPublisher automatically generates in `ORAData` classes.

In a `SQLData` scenario, you must manually provide a type map to ensure correct mapping between SQL object types and Java types. In a JDBC application, you can properly initialize the default type map for your connection or you can explicitly provide a type map as a `getObject()` input parameter.

See Also: Oracle Database JDBC Developer's Guide and Reference

In addition, note that there is no support for strongly typed object references in an `SQLData` implementation. All object references are weakly typed `java.sql.Ref` instances.

### 4.7.4 Effects of Using SQL FINAL, NOT FINAL, NOT INSTANTIABLE

This section discusses the effect of using the SQL modifiers `FINAL`, `NOT FINAL`, or `NOT INSTANTIABLE` on JPublisher-generated wrapper classes.

Using the SQL modifier `FINAL` or `NOT FINAL` on a SQL type or on a method of a SQL type has no effect on the generated Java wrapper code. This ensures that, in all cases, JPublisher users are able to customize generated Java wrapper classes by extending the classes and overriding the generated behavior.

Using the `NOT INSTANTIABLE` SQL modifier on a method of a SQL type results in no code being generated for that method in the Java wrapper class. Therefore, to call such a method, you must cast to some wrapper class that corresponds to an instantiable SQL subtype.

Using `NOT INSTANTIABLE` on a SQL type results in the corresponding wrapper class being generated with `protected` constructors. This will remind you that instances of that class can be created only through subclasses that correspond to the instantiable SQL types.